home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / GRAPHICS / FRAMES.ZIP / FRAMES.C next >
Encoding:
C/C++ Source or Header  |  1996-10-10  |  16.4 KB  |  742 lines

  1. /*----------------------------------------------------------------------*/
  2. /*    Frames.c        Example of how to use coordinte frames in a 3d world
  3. /* Jaime del Palacio CIS: 73072,3134    (c) Copyright 1996
  4. /* http://ourworld.compuserve.com/homepages/jdp_Site/
  5. /* This example shows how to use the notion of frames of reference
  6. /* to simplify the transformations between OCS, WCS, CCS, etc.
  7. /* also shows how to specify rotations in local axis to have
  8. /* a coherent rotation direction always
  9. /* This example is that _an example_ it is not optimized nor the best
  10. /*    possible way to implement it;
  11.  
  12. /* This program was compiled using BC 4.5 in small memory model
  13. /* and should work on any vga.
  14. /*----------------------------------------------------------------------*/
  15. /* include files */
  16. #include <MATH.h>
  17. #include <STDLIB.h>
  18. #include <STDIO.h>
  19. #include <CONIO.h>
  20. #include <MEM.h>
  21.  
  22. /*----------------------------------------------------------------------*/
  23. /* type definition */
  24.  
  25. #define BYTE unsigned char
  26.  
  27. typedef enum { FALSE, TRUE } BOOL;
  28. // Simple 3D vector structure
  29. typedef struct
  30. {
  31.     float x,y,z;
  32. } tVector;
  33.  
  34. // a 3x3 rotation matrix
  35. typedef struct
  36. {
  37.     float element[3][3];
  38. } t3x3Mat;
  39.  
  40. // a frame description scructure
  41. typedef struct
  42. {
  43.     tVector        Translation;
  44.     t3x3Mat     Rotation;
  45. } tFrame;
  46.  
  47. typedef struct
  48. {
  49.     int x,y;
  50. } tScreen;
  51.  
  52.  
  53.  
  54. /*----------------------------------------------------------------------*/
  55. /* Constants & definitions */
  56.  
  57. #define    NumVertices  4
  58.  
  59.     const tVector    unitX = { 1, 0, 0 };
  60.     const tVector    unitY = { 0, 1, 0 };
  61.     const tVector    unitZ = { 0, 0, 1 };
  62.     const tVector    zero  = { 0, 0, 0 };
  63.  
  64.     const t3x3Mat identMatrix = { 1.f,0.f,0.f ,
  65.                                   0.f,1.f,0.f ,
  66.                                   0.f,0.f,1.f };
  67.  
  68.     static const float viewDist = 128;    // distance of the viewer
  69.  
  70.     const tVector planeData[NumVertices] = { {0,0,0}, {1,0,0}, {0,1,0}, {0,0,1}};
  71.  
  72.     const float minZ = -1.f;
  73.  
  74. // screen constants for the mode
  75. #define SCREEN_CENTERX    160
  76. #define SCREEN_CENTERY    100
  77.  
  78.  
  79. /*----------------------------------------------------------------------*/
  80. /* Global variables */
  81.  
  82.     unsigned char far *SCREEN = (unsigned char far*)0xA0000000L;
  83.     float    sinTbl[360];
  84.     float    cosTbl[360];
  85.  
  86.     tFrame *frames[2];
  87.     int curFrame;
  88.     int local;
  89.  
  90.     tVector    v[NumVertices];
  91.     tScreen    s[NumVertices];
  92.  
  93. /*----------------------------------------------------------------------*/
  94. /* Prototypes */
  95.  
  96. /*----------------------------------------------------------------------*/
  97. /* Code */
  98.  
  99.  
  100. /*-------------------------------------*/
  101. /* Graphics functions */
  102.  
  103. // SetMode: Set the video mode to 'mode'
  104. void SetMode( BYTE mode )
  105. {
  106.     asm
  107.     {
  108.         mov ax,0
  109.         mov al,mode
  110.         int 0x10
  111.     }
  112. } // SetMode
  113.  
  114. // Putpixel: draws a pixel of at x,y of SCREEN (320x200) assumed
  115. void PutPixel( unsigned char far *SCREEN, int x, int y, BYTE color )
  116. {
  117.     SCREEN[(y<<8)+(y<<6)+x] = color;
  118. } // PutPixel
  119.  
  120. void ClearScreen( BYTE far * SCREEN )
  121. {
  122.     _fmemset( SCREEN, 0, (size_t)64000L );
  123. }
  124.  
  125. void Line(unsigned char far *Screen, int X1, int Y1, int X2,int Y2, int Color)
  126. {
  127.   unsigned int   X_Unit, Y_Unit, XDiff, YDiff, Error;
  128.   asm{
  129.                 CLD
  130.                 Mov  Ax, WORD [Screen+2]
  131.                 Mov  ES, Ax
  132.                 Mov  Ax, Y1
  133.                 Mov  Dx, 320
  134.                 Mul  Dx
  135.                 Add  Ax, X1
  136.                 Add  Ax, WORD [Screen]
  137.                 Mov  Bx, Ax
  138.   }
  139.         InitL :
  140.   asm{
  141.                 Mov  Dx, Color
  142.                 Mov  Error, 0
  143.                 Mov  Ax, Y2
  144.                 Sub  Ax, Y1
  145.                 JNS  YPos
  146.                 Mov  Y_Unit, -320
  147.                 Neg  Ax
  148.                 Mov  YDiff, Ax
  149.                 Jmp  Next
  150.   }
  151.         YPos  :
  152.   asm{
  153.                 Mov  Y_Unit, 320
  154.                 Mov  YDiff, Ax
  155.   }
  156.   Next  :
  157.   asm {
  158.                 Mov  Ax, X2
  159.                 Sub  Ax, X1
  160.                 JNS  XPos
  161.                 Mov  X_Unit, -1
  162.                 Neg  Ax
  163.                 Mov  XDiff, Ax
  164.                 Jmp  Next2
  165.   }
  166.         XPos  :
  167.   asm{
  168.                 Mov  X_Unit, 1
  169.                 Mov  XDiff, Ax
  170.   }
  171.          Next2 :
  172.   asm{
  173.                 Cmp  Ax, YDiff
  174.                 JC   YLine
  175.                 Jmp  XLine
  176.   }
  177.         XLine :
  178.   asm{
  179.                 Mov  Cx,XDiff
  180.                 Inc  Cx
  181.   }
  182.          XLine1:
  183.   asm{
  184.                 Mov  ES:[Bx], Dl
  185.                 Add  Bx, X_Unit
  186.                 Mov  Ax, Error
  187.                 Add  Ax, YDiff
  188.                 Mov  Error, Ax
  189.                 Sub  Ax, XDiff
  190.                 JC   XLine2
  191.                 Mov  Error, Ax
  192.                 Add  Bx, Y_Unit
  193.   }
  194.         XLine2:
  195.   asm{
  196.                 Loop XLine1
  197.                 Jmp  LDone
  198.   }
  199.          YLine :
  200.   asm{
  201.                 Mov  Cx, YDiff
  202.                 Inc  Cx
  203.   }
  204.          YLine1:
  205.   asm{
  206.                 Mov  Es:[Bx], Dl
  207.                 Add  Bx, Y_Unit
  208.                 Mov  Ax, Error
  209.                 Add  Ax, XDiff
  210.                 Mov  Error, Ax
  211.                 Sub  Ax, YDiff
  212.                 JC   YLine2
  213.                 Mov  Error, Ax
  214.                 Add  Bx, X_Unit
  215.   }
  216.         YLine2:
  217.   asm{
  218.                 Loop YLine1
  219.   }
  220.          LDone :
  221.   asm{
  222.                 And  Ax,Ax
  223.   }
  224. }
  225.  
  226.  
  227. tScreen ToScreen( tVector v )
  228. {
  229.     tScreen s;
  230.     float projK;
  231.     s.x = 0; s.y = 0;
  232.     if ( v.z >= minZ )
  233.         return s;
  234.    // perspective proyection using right handed coord. system
  235.    projK = (float)viewDist / v.z;
  236.    s.x = (int)(-v.x * projK) + SCREEN_CENTERX;
  237.    s.y = (int)((v.y * projK)) + SCREEN_CENTERY;
  238.  
  239.    // simple clipping here
  240.    if ( s.x >= 320 )
  241.     s.x = 319;
  242.    if ( s.x < 0 )
  243.     s.x = 0;
  244.    if ( s.y >= 200 )
  245.     s.y = 199;
  246.    if ( s.y < 0 )
  247.     s.y = 0;
  248.     // done
  249.    return s;
  250. } // ToScreen
  251.  
  252. /*-------------------------------------*/
  253. /* Math & table funtions */
  254. /* some math functions for matrices and vectors */
  255.  
  256.  
  257. #define RAD(x) ((float)(x)*M_PI / 180)
  258.  
  259.  
  260. void MakeSinCosTables( void )
  261. {
  262.     int j;
  263.     for (j=0; j<360; j++)
  264.     {
  265.         sinTbl[j] = sin(RAD(j));
  266.         cosTbl[j] = cos(RAD(j));
  267.     }
  268. } // MakeSinCosTalbes
  269.  
  270.  
  271. tVector vector( float x, float y, float z )
  272. {
  273.     tVector v;
  274.     v.x = x;
  275.     v.y = y;
  276.     v.z = z;
  277.     return v;
  278. }
  279.  
  280. float Len( tVector v )
  281. {
  282.    return ( sqrt(v.x*v.x + v.y*v.y + v.z*v.z) );
  283.  
  284. } /* Len */
  285.  
  286.  
  287. tVector Normalize( tVector v )
  288. {
  289.    float a;
  290.    if( (a = Len(v)) == 0)
  291.       return vector(0.f,0.f,0.f);
  292.    return vector( v.x/a, v.y/a, v.z/a );
  293. } /* Normalize */
  294.  
  295.  
  296. // adds to vectors and puts the result in v1
  297. tVector AddVector( tVector v1, tVector v2 )
  298. {
  299.     v1.x += v2.x;
  300.     v1.y += v2.y;
  301.     v1.z += v2.z;
  302.    // done
  303.    return v1;
  304. }
  305.  
  306. /* --------------------------------------------------------- */
  307. /* operator *(t3x3Mat, tVector): multiply a vector times a matrix
  308. /* --------------------------------------------------------- */
  309. tVector PreMatMul( tVector v, t3x3Mat mat )
  310. {
  311.     tVector r;
  312.     r.x = v.x * mat.element[0][0] + v.y * mat.element[1][0] + v.z * mat.element[2][0];
  313.     r.y = v.x * mat.element[0][1] + v.y * mat.element[1][1] + v.z * mat.element[2][1];
  314.     r.z = v.x * mat.element[0][2] + v.y * mat.element[1][2] + v.z * mat.element[2][2];
  315.     return r;
  316. }
  317.  
  318. /* --------------------------------------------------------- */
  319. /* operator *(t3x3Mat, tVector): multiply a matrix times a vector
  320. /* --------------------------------------------------------- */
  321. tVector PostMatMul( t3x3Mat mat, tVector v )
  322. {
  323.     tVector r;
  324.     r.x = mat.element[0][0] * v.x + mat.element[0][1]* v.y + mat.element[0][2] * v.z;
  325.     r.y = mat.element[1][0] * v.x + mat.element[1][1]* v.y + mat.element[1][2] * v.z;
  326.     r.z = mat.element[2][0] * v.x + mat.element[2][1]* v.y + mat.element[2][2] * v.z;
  327.     return r;
  328. }
  329.  
  330. /* --------------------------------------------------------- */
  331. /* operator *(t3x3Mat, t3x3Mat): multiply two matrices
  332. /* --------------------------------------------------------- */
  333. t3x3Mat MatMul(t3x3Mat m1, t3x3Mat m2 )
  334. {
  335.     t3x3Mat r;
  336.     int i,j,k;
  337.     for( i=0; i<3; i++ )
  338.         for( j=0; j<3; j++ )
  339.         {
  340.             r.element[i][j] = 0.f;
  341.             for( k=0; k<3; k++ )
  342.                 r.element[i][j] += m1.element[i][k] * m2.element[k][j];
  343.         }
  344.     return r;
  345. };
  346.  
  347.  
  348.  
  349. // newFrame: creates a new frame aligned with the world and at the origin
  350. tFrame *NewFrame( void )
  351. {
  352.     tFrame    *f;
  353.  
  354.     // get some memory
  355.     if ((f = (tFrame*)malloc(sizeof( tFrame) ))==NULL)
  356.         return NULL;
  357.     // intialize the frame aligned with the WCS
  358.     f->Rotation = identMatrix;
  359.     // translate the frame
  360.     f->Translation = zero;
  361.  
  362.     return f;
  363. } // NewFrame
  364.  
  365. /*-------------------------------------*/
  366. /* 3D funtions */
  367.  
  368. t3x3Mat YawMat( int deg )
  369. {
  370.     t3x3Mat r = identMatrix;
  371.     float c = cosTbl[deg];
  372.     float s = sinTbl[deg];
  373.     r.element[0][0] = c;
  374.     r.element[0][2] = s;
  375.     r.element[2][0] = -s;
  376.     r.element[2][2] = c;
  377.     return r;
  378. };
  379.  
  380.  
  381. t3x3Mat PitchMat( int deg )
  382. {
  383.     t3x3Mat r = identMatrix;
  384.     float c = cosTbl[deg];
  385.     float s = sinTbl[deg];
  386.     r.element[1][1] = c;
  387.     r.element[1][2] = -s;
  388.     r.element[2][1] = s;
  389.     r.element[2][2] = c;
  390.     return r;
  391. };
  392.  
  393. t3x3Mat RollMat( int deg )
  394. {
  395.     t3x3Mat r = identMatrix;
  396.     float c = cosTbl[deg];
  397.     float s = sinTbl[deg];
  398.     r.element[0][0] = c;
  399.     r.element[0][1] = -s;
  400.     r.element[1][0] = s;
  401.     r.element[1][1] = c;
  402.     return r;
  403. };
  404.  
  405.  
  406.  
  407.  
  408.  
  409. // Transform from local frame coordinates to world coordinates
  410. tVector ToGlobal( tFrame f, tVector v )
  411. {
  412.     // apply rotation
  413.     v = PostMatMul( f.Rotation, v );
  414.     // translate
  415.     v.x += f.Translation.x;
  416.     v.y += f.Translation.y;
  417.     v.z += f.Translation.z;
  418.     // done
  419.     return v;
  420. } // ToGlobal
  421.  
  422. // Transform from World coordinates to local frame coordinates
  423. tVector ToLocal( tFrame f, tVector v )
  424. {
  425.     // translate
  426.     v.x -= f.Translation.x;
  427.     v.y -= f.Translation.y;
  428.     v.z -= f.Translation.z;
  429.     // apply rotation
  430.     v = PreMatMul( v, f.Rotation );
  431.     // done
  432.     return v;
  433. } // ToLocal
  434.  
  435. // Transform just the direction part from local to world coords.
  436. tVector DirToGlobal( tFrame f, tVector v )
  437. {
  438.     v = PostMatMul( f.Rotation, v );
  439.     return v;
  440. } // DirToGlobal
  441.  
  442. // Transform just the direction part from world to local coords.
  443. tVector DirToLocal( tFrame f , tVector v )
  444. {
  445.     v = PreMatMul( v, f.Rotation );
  446.     return v;
  447. } // DirToGlobal
  448.  
  449.  
  450. void RotateFrameGlobal( tFrame *f, char axis, int deg )
  451. {
  452.  
  453.     t3x3Mat newRotation;
  454.  
  455.     // adjust degrees to the tables
  456.     if ( deg > 360 )
  457.         deg = deg % 360;
  458.     if ( deg < 0 )
  459.         deg = ( deg + 360 ) % 360;
  460.  
  461.  
  462.     switch( axis )
  463.     {
  464.     case 'x':
  465.         newRotation = PitchMat( deg );
  466.         break;
  467.     case 'y':
  468.         newRotation = YawMat( deg );
  469.         break;
  470.     case 'z':
  471.         newRotation = RollMat( deg );
  472.         break;
  473.     default:
  474.         newRotation = identMatrix;
  475.         break;
  476.     }
  477.     // concatenate with the old rotation
  478.     f->Rotation = MatMul( newRotation, f->Rotation );
  479.     // done
  480. } // RotateFrame
  481.  
  482.  
  483. // rotate a frame by 'deg' degrees arround and arbitrary
  484. // axis defined by the vector v
  485. void RotateFrameLocal( tFrame* f, char ax, int deg )
  486. {
  487.     tVector axis;
  488.     float s,c,k;
  489.     t3x3Mat mat;
  490.  
  491.     switch( ax )
  492.     {
  493.     case 'x':
  494.         axis = DirToGlobal( *f, unitX );
  495.         break;
  496.     case 'y':
  497.         axis = DirToGlobal( *f, unitY );
  498.         break;
  499.     case 'z':
  500.         axis = DirToGlobal( *f, unitZ );
  501.         break;
  502.     default:
  503.         return;
  504.     }
  505.  
  506.     // axis most be a unitary vector
  507.     axis = Normalize( axis );
  508.  
  509.     // wrap arround
  510.     if ( deg > 360 )
  511.         deg = deg % 360;
  512.     if ( deg < 0 )
  513.         deg = ( deg + 360 ) % 360;
  514.  
  515.     // now compute the general rotation matrix
  516.     s = (deg>=0?sinTbl[deg]:-sinTbl[deg]);
  517.     c = (deg>=0?cosTbl[deg]:-cosTbl[deg]);
  518.     k = 1.f-c;
  519.  
  520.     mat.element[0][0] = k*axis.x*axis.x + c;
  521.     mat.element[0][1] = k*axis.x*axis.y-s*axis.z;
  522.     mat.element[0][2] = k*axis.x*axis.z + s*axis.y;
  523.     mat.element[1][0] = k*axis.x*axis.y + s*axis.z;
  524.     mat.element[1][1] = k*axis.y*axis.y + c;
  525.     mat.element[1][2] = k*axis.y*axis.z - s*axis.x;
  526.     mat.element[2][0] = k*axis.x*axis.z - s*axis.y;
  527.     mat.element[2][1] = k*axis.y*axis.z + s*axis.x;
  528.     mat.element[2][2] = k*axis.z*axis.z + c;
  529.     // concatenate this rotation with the current matrix
  530.     f->Rotation  = MatMul( mat , f->Rotation );
  531.  
  532.     // done
  533.     return;
  534.  
  535. }
  536.  
  537.  
  538. void TranslateFrame( tFrame *f, float X, float Y, float Z )
  539. {
  540.     f->Translation.x += X;
  541.     f->Translation.y += Y;
  542.     f->Translation.z += Z;
  543. } // TranslateFrame
  544.  
  545.  
  546. /*-------------------------------------*/
  547. /* Others */
  548.  
  549. // transfor all vertices to screen pixels
  550. void RenderScreen( BYTE far *SCREEN )
  551. {
  552.     int j;
  553.  
  554.     // copy all point to the temporal structure
  555.     for (j=0; j<NumVertices; j++)
  556.     {
  557.         v[j].x = planeData[j].x;
  558.         v[j].y = planeData[j].y;
  559.         v[j].z = planeData[j].z;
  560.     }
  561.  
  562.     for (j=0; j<NumVertices; j++)
  563.     {
  564.         // Transform vertices to Global frame
  565.         v[j] = ToGlobal( *frames[0], v[j] );
  566.         // Transform vertices to Camera frame
  567.         v[j] = ToLocal( *frames[1], v[j] );
  568.         // project vertices
  569.         s[j] = ToScreen( v[j] );
  570.     }
  571.  
  572.     // draw a frame shape 0-1, 0-2, 0-3
  573.     Line( SCREEN, s[0].x, s[0].y, s[1].x, s[1].y, 10 );
  574.     Line( SCREEN, s[0].x, s[0].y, s[2].x, s[2].y, 11 );
  575.     Line( SCREEN, s[0].x, s[0].y, s[3].x, s[3].y, 12 );
  576.  
  577.  
  578.     // render state text
  579.     gotoxy(1,23);
  580.     printf("currFrame: %s\nlocal: %d",( curFrame==0?"plane":"camera"),
  581.         local );
  582.  
  583.     // done for this frame
  584.     return;
  585.  
  586. }  // RenderScreen
  587.  
  588. void InitAll( void )
  589. {
  590.     // Make math LUTs
  591.     MakeSinCosTables();
  592.     //init frames
  593.     frames[0] = NewFrame();
  594.     TranslateFrame( frames[0], 0.f, 0.f, -3.f );
  595.     frames[1] = NewFrame();
  596.     // done
  597.     return;
  598. } // InitAll
  599.  
  600.  
  601.  
  602. void DoneAll( void )
  603. {
  604.     free( frames[0] );
  605.     free( frames[1] );
  606.     // done
  607.    return;
  608. }
  609.  
  610.  
  611. void SplashPlate( void )
  612. {
  613.     clrscr();
  614.     printf("Frame.exe  Frames sample (c) Copyright 1996 Jaime del Palacio\n");
  615.     printf("This program shows the concept of using frames of reference\n");
  616.     printf("to simplify the management of 3d transformations.\n" );
  617.     printf("It also shows how to rotates frames with resprect of their local axis\n");
  618.     printf("to mantain visual coherence. This technique is very\n");
  619.     printf("simple and clear (IMO) for use in any type of 3D engine.\n");
  620.     printf("Warning: No clipping is implemented so don't go out of sight\n");
  621.     printf("If you have any questions, comments or whatever, send me e-mail to\n");
  622.     printf("Compuserve: 73072,3134\n");
  623.     printf("Internet: 73072.3134@compuserve.com\n");
  624.     printf("home page: http://ourworld.compuserve.com/homepages/jdp_Site/\n\n");
  625.     printf("Usage:\n");
  626.     printf("<Y> +Yaw <y> -Yaw\n");
  627.     printf("<P> +Pitch <p> -Pitch\n");
  628.     printf("<R> +Roll <r> -Roll\n");
  629.     printf("<A> move in the +Z direction\n");
  630.     printf("<Z> move in the -Z direction\n");
  631.     printf("<F> change current frame\n");
  632.     printf("<L> toggle local rotations on & off\n" );
  633.     printf("<ESC> Quit\n");
  634.     printf("Have fun!\n");
  635.     printf("Press any key");
  636.  
  637.     getch();
  638.  
  639.     // done
  640.     return;
  641. }
  642.  
  643. void main(void)
  644. {
  645.     char     key;
  646.     tVector deltaT;
  647.     // number of degrees per arrow hit
  648.     static int degPerStep = 3;
  649.     local = 0;
  650.  
  651.     // print helpscreen first
  652.     SplashPlate();
  653.  
  654.     // set up 320x200 256 colors
  655.     SetMode( 0x13 );
  656.  
  657.     // Initialize all fremes and vertices
  658.     InitAll();
  659.     // main loop
  660.     do
  661.     {
  662.         ClearScreen(SCREEN);
  663.         RenderScreen(SCREEN);
  664.         // process input and logic here
  665.         key = getch();
  666.         switch (key)
  667.         {
  668.         // yaw rotation
  669.         case 'y':
  670.             if( local )
  671.                 RotateFrameLocal( frames[curFrame], 'y', degPerStep );
  672.             else
  673.                 RotateFrameGlobal( frames[curFrame], 'y', degPerStep );
  674.             break;
  675.         case 'Y':
  676.             if( local )
  677.                 RotateFrameLocal( frames[curFrame], 'y', -degPerStep );
  678.             else
  679.                 RotateFrameGlobal( frames[curFrame], 'y', -degPerStep );
  680.             break;
  681.         // pitch
  682.         case 'p':
  683.             if( local )
  684.                 RotateFrameLocal( frames[curFrame], 'x', degPerStep );
  685.             else
  686.                 RotateFrameGlobal( frames[curFrame], 'x', degPerStep );
  687.             break;
  688.         case 'P':
  689.             if( local )
  690.                 RotateFrameLocal( frames[curFrame], 'x', -degPerStep );
  691.             else
  692.                 RotateFrameGlobal( frames[curFrame], 'x', -degPerStep );
  693.             break;
  694.         // roll
  695.         case 'r':
  696.             if( local )
  697.                 RotateFrameLocal( frames[curFrame], 'z', degPerStep );
  698.             else
  699.                 RotateFrameGlobal( frames[curFrame], 'z', degPerStep );
  700.             break;
  701.         case 'R':
  702.             if( local )
  703.                 RotateFrameLocal( frames[curFrame], 'z', -degPerStep );
  704.             else
  705.                 RotateFrameGlobal( frames[curFrame], 'z', -degPerStep );
  706.             break;
  707.         // switch to next frame
  708.         case 'f':
  709.         case 'F':
  710.             curFrame = (curFrame == 0)? 1 : 0;
  711.         break;
  712.         // translation of the local frame
  713.         // a moves the frame in the local -Z direction
  714.         case 'a':
  715.         case 'A':
  716.             if( local )
  717.                 deltaT = DirToGlobal( *frames[curFrame], unitZ );
  718.             else
  719.                 deltaT = unitZ;
  720.             TranslateFrame( frames[curFrame], -deltaT.x, -deltaT.y, -deltaT.z );
  721.             break;
  722.         // z moves the frame in the local Z direction
  723.         case 'z':
  724.         case 'Z':
  725.             if( local )
  726.                 deltaT = DirToGlobal( *frames[curFrame], unitZ );
  727.             else
  728.                 deltaT = unitZ;
  729.             TranslateFrame( frames[curFrame], deltaT.x, deltaT.y, deltaT.z );
  730.             break;
  731.         case 'l':
  732.         case 'L':
  733.             local = local==0?1:0;
  734.             break;
  735.         };
  736.     } while ( key != 27 );
  737.     DoneAll();
  738.     // set text mode
  739.     SetMode( 0x03 );
  740. }
  741. /* eof : Frames.c */
  742.